﻿using System.CodeDom;

namespace WeaverCustomTool
{
    public struct DeferEditionPropertyDeclaration
    {
        private readonly CodeMemberProperty property;
        private readonly CodeTypeDeclaration type;

        public DeferEditionPropertyDeclaration(CodeMemberProperty property, CodeTypeDeclaration type)
        {
            this.property = property;
            this.type = type;
        }

        public void ImplementDeferEdition()
        {
            var editionPropertyName = property.Name + "ForEdition";
            var editionFieldName = editionPropertyName.ToCamelCase();
            var editionField = new CodeMemberField(property.Type, editionFieldName);
            var editionProperty = new CodeMemberProperty()
                {
                    Name = editionPropertyName,
                    Type = property.Type,
                    HasGet = true,
                    HasSet = true
                };

            var editionFieldReference = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), editionFieldName);
            editionProperty.GetStatements.Add(new CodeMethodReturnStatement(editionFieldReference));
            editionProperty.SetStatements.Add(new CodeAssignStatement(editionFieldReference, new CodePropertySetValueReferenceExpression()));
            editionProperty.ImplementINotifyPropertyChanged();

            type.Members.Add(editionField);
            type.Members.Add(editionProperty);

            var comitMethod = new MethodDeclaration(type).GetMethodOrDefault("ComitEdition");
            if(comitMethod == null)
            {
                comitMethod = new CodeMemberMethod() { Name = "ComitEdition" };
                type.Members.Add(comitMethod);
            }

            var resetMethod = new MethodDeclaration(type).GetMethodOrDefault("ResetEdition");
            if (resetMethod == null)
            {
                resetMethod = new CodeMemberMethod() { Name = "ResetEdition" };
                type.Members.Add(resetMethod);
            }

            resetMethod.Statements.Add(new CodeAssignStatement(
                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), editionPropertyName),
                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), property.Name)));

            comitMethod.Statements.Add(new CodeAssignStatement(
                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), property.Name),
                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), editionPropertyName)));
        }
    }
}
